package cn.bud.msgbus.server.client;

import cn.bud.msgbus.server.busdao.SubscriberMapper;
import cn.bud.msgbus.server.server.subscribe.LocalSubscribe;
import cn.bud.msgbus.server.server.subscribe.LocalSubscriber;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * BusProviderScaner
 *
 * @author hxj
 * @version 1.0
 * @description
 * @date 2024-07-15 8:59
 */
@Component
public class BusCustomerScanner implements SubscriberMapper<LocalSubscriber> {

    public ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
//    @javax.annotation.Resource
//    private ProviderHandler providerHandler;
//
//
//    String[] scanPackages = new String[]{"com.zl9c.bus.**.subscribe"};
//
//    public List<ProviderProxy> scanProviders() throws IOException, ClassNotFoundException {
//        List<ProviderProxy> proxies = new ArrayList<>();
//        for (String scanPackage : scanPackages) {
//            List<Class<?>> clazzList = scanProviders(scanPackage);
//            for (Class<?> clazz : clazzList) {
//                ProviderProxy proxy = new ProviderProxy(clazz, providerHandler);
//                proxies.add(proxy);
//            }
//        }
//        return proxies;
//    }
//
//    public List<Class<?>> scanProviders(String packagePath) throws IOException, ClassNotFoundException {
//        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
//        String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
//                + ClassUtils.convertClassNameToResourcePath(packagePath) + "/*.class";
////    以上代码可解析出当前工程所引用的jar包中的类
////    以下代码却不可以解析jar中的类，本地IDEA中测试没有问题，工程里直接引用的sub module, 但Linux上就找不着了
////     Resource[] resources = resolver.getResources("classpath*:org\\yourpackage\\*.class");
//
//        Resource[] resources = resolver.getResources(pattern);
//        CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
//
////     ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//
//        List<Class<?>> list = new ArrayList<>();
//        for (Resource resource : resources) {
//            //全限定类名，完整路径
//            String className = readerFactory.getMetadataReader(resource).getClassMetadata().getClassName();
////         Class<?> aClass = systemClassLoader.loadClass(className); //在linux上是出现找不到类的异常，并不是由这个ClassLoader加载的
//            Class<?> aClass = Class.forName(className);//直接使用Class.forName 即可加载出来
//            if ( aClass.isAnnotationPresent(LocalSubscribe.class)) {
//                list.add(aClass);
//            }
//        }
//        return list;
//    }

    @Override
    public List<LocalSubscriber> listSubscriber() {
        Map<String, Object> objectMap = applicationContext.getBeansWithAnnotation(LocalSubscribe.class);
        if (MapUtils.isEmpty(objectMap)) {
            return null;
        }
        List<LocalSubscriber> list = new ArrayList<>();
        for (Map.Entry<String, Object> entry : objectMap.entrySet()) {
//            String className = entry.getKey();
            Object obj = entry.getValue();
            for (Method method : obj.getClass().getMethods()) {
                LocalSubscriber ls = new LocalSubscriber();
//                if (!method.isAnnotationPresent(LocalSubscribe.class)) {
//                    continue;
//                }
                LocalSubscribe lsAnno = AnnotationUtils.findAnnotation(method, LocalSubscribe.class);
                if (lsAnno == null) {
                    continue;
                }
                ls.addTopic(lsAnno.mainTopic(), null, null);
                ls.setDataClazz(lsAnno.dataClazz());
//                ls.setAsync(lsAnno.async());
                ls.setHandler(obj);
                ls.setMethod(method);
                list.add(ls);
            }
        }
        return list;
    }
}
